#include "dc_serial_screen.h"
#include <rtdevice.h>

static rt_device_t screen_uart = RT_NULL;
static rt_sem_t screen_tx_sem = RT_NULL;
static rt_mutex_t screen_mutex = RT_NULL;
static uint8_t tx_buffer[DC_SCREEN_BUFFER_SIZE];
static uint8_t rx_buffer[DC_SCREEN_BUFFER_SIZE];

/* 大彩屏通信协议帧结构 */
typedef struct {
    uint8_t header[2];      /* 帧头: 0xAA, 0x55 */
    uint8_t command;        /* 指令 */
    uint8_t length;         /* 数据长度 */
    uint8_t data[250];      /* 数据 */
    uint8_t checksum;       /* 校验和 */
} dc_frame_t;

/* 计算校验和 */
static uint8_t calculate_checksum(uint8_t *data, uint8_t len)
{
    uint8_t sum = 0;
    for (uint8_t i = 0; i < len; i++) {
        sum += data[i];
    }
    return sum;
}

/* 发送数据到屏幕 */
static rt_err_t screen_send_data(uint8_t *data, uint8_t len)
{
    rt_size_t sent_len;
    
    if (screen_uart == RT_NULL) {
        return RT_ERR_IO;
    }
    
    /* 等待发送信号量 */
    if (rt_sem_take(screen_tx_sem, RT_WAITING_FOREVER) != RT_EOK) {
        return RT_ERR_BUSY;
    }
    
    /* 发送数据 */
    sent_len = rt_device_write(screen_uart, 0, data, len);
    
    /* 释放信号量 */
    rt_sem_release(screen_tx_sem);
    
    return (sent_len == len) ? RT_OK : RT_ERR_IO;
}

/* 构建并发送指令帧 */
static rt_err_t send_command_frame(uint8_t cmd, uint8_t *data, uint8_t data_len)
{
    dc_frame_t frame;
    uint8_t frame_len;
    
    if (data_len > 250) {
        return RT_ERR_PARAM;
    }
    
    /* 构建帧头 */
    frame.header[0] = 0xAA;
    frame.header[1] = 0x55;
    frame.command = cmd;
    frame.length = data_len;
    
    /* 复制数据 */
    if (data_len > 0 && data != RT_NULL) {
        rt_memcpy(frame.data, data, data_len);
    }
    
    /* 计算校验和 */
    frame.checksum = calculate_checksum(&frame.command, data_len + 2); /* cmd + len + data */
    
    /* 发送整个帧 */
    frame_len = 4 + data_len; /* header(2) + cmd(1) + len(1) + data + checksum(1) */
    return screen_send_data((uint8_t*)&frame, frame_len);
}

/* 屏幕数据接收回调 */
static rt_err_t screen_rx_callback(rt_device_t dev, rt_size_t size)
{
    /* 处理屏幕发送的数据（如按钮事件等） */
    rt_size_t read_len = rt_device_read(dev, 0, rx_buffer, size);
    
    if (read_len > 0) {
        /* 解析接收到的数据帧 */
        // 这里需要根据大彩屏的实际协议进行解析
    }
    
    return RT_OK;
}

rt_err_t dc_screen_init(void)
{
    rt_err_t result;
    
    /* 查找串口设备 */
    screen_uart = rt_device_find(DC_SCREEN_UART_DEVICE);
    if (screen_uart == RT_NULL) {
        LOG_E("Screen UART device not found: %s\n", DC_SCREEN_UART_DEVICE);
        return RT_ERR_NOT_FOUND;
    }
    
    /* 配置串口参数 */
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = DC_SCREEN_BAUD_RATE;
    config.data_bits = DATA_BITS_8;
    config.stop_bits = STOP_BITS_1;
    config.parity = PARITY_NONE;
    config.bufsz = DC_SCREEN_BUFFER_SIZE;
    
    result = rt_device_control(screen_uart, RT_DEVICE_CTRL_CONFIG, &config);
    if (result != RT_OK) {
        LOG_E("Failed to configure screen UART\n");
        return result;
    }
    
    /* 打开串口设备 */
    result = rt_device_open(screen_uart, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
    if (result != RT_OK) {
        LOG_E("Failed to open screen UART\n");
        return result;
    }
    
    /* 设置接收回调 */
    rt_device_set_rx_indicate(screen_uart, screen_rx_callback);
    
    /* 创建信号量和互斥锁 */
    screen_tx_sem = rt_sem_create("screen_tx", 1, RT_IPC_FLAG_FIFO);
    screen_mutex = rt_mutex_create("screen_mutex", RT_IPC_FLAG_FIFO);
    
    if (screen_tx_sem == RT_NULL || screen_mutex == RT_NULL) {
        LOG_E("Failed to create screen synchronization objects\n");
        rt_device_close(screen_uart);
        return RT_ERR_MEM;
    }
    
    LOG_I("DC serial screen initialized successfully\n");
    return RT_OK;
}

rt_err_t dc_screen_write_register(uint16_t addr, uint16_t value)
{
    uint8_t data[4];
    
    /* 构建数据: 地址(2字节) + 值(2字节) */
    data[0] = (addr >> 8) & 0xFF;
    data[1] = addr & 0xFF;
    data[2] = (value >> 8) & 0xFF;
    data[3] = value & 0xFF;
    
    return send_command_frame(DC_CMD_WRITE_REG, data, 4);
}

rt_err_t dc_screen_write_variable(uint16_t addr, float value)
{
    uint8_t data[6];
    int16_t int_part;
    uint16_t frac_part;
    
    /* 将浮点数转换为整数和小数部分 */
    int_part = (int16_t)value;
    frac_part = (uint16_t)((value - int_part) * 100); /* 保留2位小数 */
    
    /* 构建数据: 地址(2字节) + 整数(2字节) + 小数(2字节) */
    data[0] = (addr >> 8) & 0xFF;
    data[1] = addr & 0xFF;
    data[2] = (int_part >> 8) & 0xFF;
    data[3] = int_part & 0xFF;
    data[4] = (frac_part >> 8) & 0xFF;
    data[5] = frac_part & 0xFF;
    
    return send_command_frame(DC_CMD_WRITE_VP, data, 6);
}

rt_err_t dc_screen_write_string(uint16_t addr, const char *str)
{
    uint8_t data[256];
    uint8_t str_len;
    
    if (str == RT_NULL) {
        return RT_ERR_PARAM;
    }
    
    str_len = rt_strlen(str);
    if (str_len > 250) {
        str_len = 250;
    }
    
    /* 构建数据: 地址(2字节) + 字符串 */
    data[0] = (addr >> 8) & 0xFF;
    data[1] = addr & 0xFF;
    rt_memcpy(&data[2], str, str_len);
    
    return send_command_frame(DC_CMD_WRITE_STR, data, str_len + 2);
}

rt_err_t dc_screen_change_page(screen_page_t page)
{
    uint8_t data[1];
    
    data[0] = (uint8_t)page;
    return send_command_frame(DC_CMD_UPDATE_SCREEN, data, 1);
}

rt_err_t dc_screen_update_data(void)
{
    /* 更新所有显示数据 */
    // 这个函数需要在hmi模块中具体实现
    return RT_OK;
}

rt_err_t dc_screen_send_alarm(uint8_t alarm_id, const char *alarm_msg)
{
    uint8_t data[64];
    uint8_t msg_len;
    
    if (alarm_msg == RT_NULL) {
        return RT_ERR_PARAM;
    }
    
    msg_len = rt_strlen(alarm_msg);
    if (msg_len > 60) {
        msg_len = 60;
    }
    
    /* 构建数据: 报警ID(1字节) + 报警消息 */
    data[0] = alarm_id;
    rt_memcpy(&data[1], alarm_msg, msg_len);
    
    return send_command_frame(DC_CMD_WRITE_STR, data, msg_len + 1);
}